<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    /*
    js 本身是基于面向对象开发的编程语言
    => 类、封装、继承、多态
    封装： 类也是一个函数，把实现一个功能的代码进行封装，以此实现“低耦合高内聚”
    多态：子类重写父类的方法（伴随继承运行）
    重载：相同的方法，由于参数或者返回值不同，具备了不同的功能（js中不具备严格意义的重载
    ，js中的重载：同一个方法内，根据传参不同实现不同的功能）
    继承： 子继承父类中的方法
    */
    <script>
        // /*
        // 继承的目的，让子类的实例同时也具备父类中私有的属性和公共的方法
        // js中第一种继承方案： 原型继承（让子类的原型等于父类的实例即可）
        // */
        // function parent() {
        //     this.x = 100
        // }
        // parent.prototype.getX = function getX() {
        //     return this.x
        // }
        // function child() {
        //     this.y = 200
        // }
        // child.prototype = new parent // => 原型继承

        // child.prototype.getY = function getY() {
        //     return this.y
        // }
        // let c1 = new child()
        // console.log(c1);
        // console.log(c1.getX(), c1.getY()); // 子类的实例，能够用子类私有和原型上公有的，父类的实例可以用父类私有和原型共有的，子类继承之后，可以用子类私有、父类私有..
        // let p1 = new parent()
        // console.log('p1', p1);
        // console.log('p1.getX()', p1.getX());
        // /*
        // 原型继承 
        // 1、 父类中私有和公有的属性方法，最后都变成子类实例公有的
        // 2、 和其他语言不同的是，原型继承并不会把父类的属性"拷贝"给子类，而是让子类的实例基于__proto__原型链找到自己定义的属性和方法 "指向/查找"方式的
        // 通过原型链一级一级向上查找

        // c1.__proto__.xxx = xxx 修改子类原型（原有父类的一个实例）中的内容，内容被修改后，对子类的其他实例有影响，但是对父类的实例不会有影响。
        // c1.__proto__.__proto__.xxx = xxx  直接修改的是父类的原型，这样子不仅会影响到父类的其他实例，也影响到其他子类的实例。
        // */
        // c1.__proto__.getY = function getY() {
        //     console.log('被修改了');
        //     return this.y
        // }
        // let c2 = new child()
        // console.log(c2);
        // console.log(c2.getX(), c2.getY());
        // console.log('p1', p1);
        // console.log('p1.getX()', p1.getX());
        // c1.__proto__.__proto__.getX = function getY() {
        //     console.log('父类被修改了 也影响到其他子类的实例');
        //     return this.x
        // }
        // console.log('c2', c2.getX(), c2.getY());
        // console.log('p1.getX()', p1.getX());
        

        // js中的第二种继承，call继承
        // function parent() {
        //     this.x = 100
        // }
        // parent.prototype.getX = function getX() {
        //     return this.x
        // }
        // function child() {
        //     // 在子类构造函数中，把父类当作普通方法执行（没有父类的实例，父类原型上的那些东西和他就没有关系）
        //     // this -> child 实例c1
        //     console.log('this', this);
        //     parent.call(this) 
        //     // this.x = 100 相当于强制给c1这个实例设置一个私有的属性x，属性值100，相当于让子类的实例继承了父类的私有的属性，并且也变为了子类私有的属性
        //     this.y = 200
        // }

        // child.prototype.getY = function getY() {
        //     return this.y
        // }

        // let c1 = new child
        // console.log(c1);

        // // 第三种：寄生组合式继承
        // function parent() {
        //     this.x = 100
        // }
        // parent.prototype.getX = function getX() {
        //     return this.x
        // }
        // function child() {
        //     parent.call(this) 
        //     this.y = 200
        // }
        // // child.prototype.__prototype__ = parent.prototype
        // child.prototype = Object.create(parent.prototype)
        // // 此时没有constructor 需要手动加上
        // child.prototype.constructor = child
        // child.prototype.getY = function getY() {
        //     return this.y
        // }

        // let c1 = new child
        // console.log(c1);
        // // // 创建一个空对象， 让其原型链指向obj
        // // let obj = {
        // //     lx: 'lxrequest'
        // // }
        // // console.log('obj', Object.create(obj));

       // // es6 class
    //     class parent {
    //         constructor() {
    //             this.x = 100
    //         }
    //         getX() {
    //             return this.x
    //         }
    //     }
    //     class child extends parent{
    //         constructor() {
    //             super()
    //             // super(100, 200) => 类似call继承 constructor执行传递了100，200
    //             this.y = 200
    //         }
    //         getY() {
    //             return this.y
    //         }
    //     }
    //    let c1 = new child()
    //    console.log(c1);
    </script>
</body>
</html>